home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / planner / util / clause.c next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  13.7 KB  |  567 lines

  1.  
  2. /*     
  3.  *      FILE
  4.  *         clause
  5.  *     
  6.  *      DESCRIPTION
  7.  *         Routines to manipulate qualification clauses
  8.  *      $Header: /private/postgres/src/planner/util/RCS/clause.c,v 1.20 1992/08/21 05:47:47 mer Exp $
  9.  */
  10.  
  11. /*     
  12.  *      EXPORTS
  13.  *             pull-constant-clauses
  14.  *             pull-relation-level-clauses
  15.  *             clause-relids-vars
  16.  *             clause-relids
  17.  *             nested-clause-p
  18.  *             relation-level-clause-p
  19.  *             contains-not
  20.  *             join-clause-p
  21.  *             qual-clause-p
  22.  *             function-index-clause-p
  23.  *             fix-opids
  24.  *             get_relattval
  25.  *             get_relsatts
  26.  */
  27.  
  28. #include "tmp/c.h"
  29.  
  30. #include "nodes/primnodes.h"
  31. #include "nodes/primnodes.a.h"
  32. #include "nodes/relation.h"
  33. #include "nodes/relation.a.h"
  34.  
  35. #include "planner/internal.h"
  36. #include "planner/clause.h"
  37. #include "planner/var.h"
  38. #include "planner/clauses.h"
  39.  
  40. /*    
  41.  *        pull-constant-clauses
  42.  *    
  43.  *        Scans through a list of qualifications and find those that
  44.  *        contain no variables.
  45.  *    
  46.  *        Returns a list of the appropriate clauses.
  47.  *    
  48.  */
  49.  
  50. /*  .. query_planner
  51.  */
  52. bool
  53. lambda1 (qual)
  54.      LispValue qual ;
  55. {
  56.     return(null (pull_var_clause (qual)));
  57. }
  58.  
  59. LispValue
  60. pull_constant_clauses (quals)
  61.      LispValue quals ;
  62. {
  63.     return(collect ( lambda1,quals));
  64. }
  65.  
  66. /*    
  67.  *        pull-relation-level-clauses
  68.  *    
  69.  *        Retrieve relation level clauses from a list of clauses.
  70.  *    
  71.  *        'quals' is the list of clauses
  72.  *    
  73.  *        Returns a list of all relation level clauses found.
  74.  *    
  75.  */
  76.  
  77. /*  .. query_planner
  78.  */
  79. static bool
  80. lambda2 (qual)
  81.      LispValue qual ;
  82. {
  83.     if (relation_level_clause_p (qual))
  84.       return(true);
  85.     else
  86.       return(false);
  87. }
  88.  
  89. LispValue
  90. pull_relation_level_clauses (quals)
  91.      LispValue quals ;
  92. {
  93.     return(collect (lambda2,quals));
  94. }
  95.  
  96. /*    
  97.  *        clause-relids-vars
  98.  *    
  99.  *        Retrieves relids and vars appearing within a clause.
  100.  *        Returns ((relid1 relid2 ... relidn) (var1 var2 ... varm)) where 
  101.  *        vars appear in the clause  this is done by recursively searching
  102.  *        through the left and right operands of a clause.
  103.  *    
  104.  *        Returns the list of relids and vars.
  105.  *    
  106.  *        XXX take the nreverse's out later
  107.  *    
  108.  */
  109.  
  110. /*  .. add-clause-to-rels   */
  111.  
  112.  
  113. LispValue
  114. clause_relids_vars (clause)
  115.      LispValue clause ;
  116. {
  117.     LispValue vars = pull_var_clause (clause);
  118.     LispValue retval = LispNil;
  119.     LispValue var_list = LispNil;
  120.     LispValue varno_list = LispNil;
  121.     LispValue tvarlist = LispNil;
  122.     LispValue i = LispNil;
  123.  
  124.     foreach (i,vars) 
  125.       tvarlist = nappend1(tvarlist,lispInteger((int)get_varno((Var)CAR(i))));
  126.     
  127.     varno_list = nreverse(remove_duplicates (tvarlist,equal));
  128.     var_list = nreverse (remove_duplicates (vars, var_equal));
  129.  
  130.     retval = lispCons (varno_list,
  131.                lispCons(var_list,LispNil));
  132.     
  133.     return(retval);
  134. }
  135.  
  136. /*    
  137.  *    NumRelids
  138.  *        (formerly clause-relids)
  139.  *    
  140.  *        Returns the number of different relations referenced in 'clause'.
  141.  */
  142.  
  143. /*  .. compute_selec   */
  144.  
  145. int
  146. NumRelids (clause)
  147.      Expr clause ;
  148. {
  149.     LispValue t_list = LispNil;
  150.     LispValue temp = LispNil;
  151.     Var var = (Var)NULL;
  152.     LispValue i = LispNil;
  153.  
  154.     foreach (i,pull_var_clause((LispValue)clause)) {
  155.     var = (Var)CAR(i);
  156.     t_list = nappend1(t_list,lispInteger(get_varno(var)));
  157.     }
  158.     t_list = remove_duplicates(t_list,equal);
  159.  
  160.     return(length(t_list));
  161.  
  162. }
  163.  
  164. /*  .. add-clause-to-rels, in-line-lambda%598037258, relation-level-clause-p
  165.  */
  166.  
  167. bool
  168. relation_level_clause_p (clause)
  169.      LispValue clause ;
  170. {
  171.     if (!single_node(clause) &&
  172.         (( is_clause(clause) &&
  173.            get_oprelationlevel((Oper)get_op(clause))) ||
  174.          (not_clause(clause) && 
  175.           relation_level_clause_p(get_notclausearg(clause))) ||
  176.          (or_clause (clause) && 
  177.           some (relation_level_clause_p ,get_orclauseargs(clause)) ) ))
  178.       return(true);
  179.     else
  180.       return(false);
  181. }
  182.  
  183. /*    
  184.  *        contains-not
  185.  *    
  186.  *        Returns t iff the clause is a 'not' clause or if any of the
  187.  *        subclauses within an 'or' clause contain 'not's.
  188.  *    
  189.  */
  190.  
  191. /*  .. add-clause-to-rels
  192.  */
  193. bool
  194. contains_not (clause)
  195.      LispValue clause ;
  196. {
  197.     if (!single_node(clause) &&
  198.         (not_clause(clause) || 
  199.          (or_clause(clause) && some( contains_not,
  200.                     get_orclauseargs(clause)))))
  201.       return(true);
  202.     else
  203.       return(false);
  204. }
  205.  
  206. /*    
  207.  *        join-clause-p
  208.  *    
  209.  *        Returns t iff 'clause' is a valid join clause.
  210.  *    
  211.  */
  212.  
  213. /*  .. in-line-lambda%598037345, in-line-lambda%598037346
  214.  *  .. initialize-join-clause-info, other-join-clause-var
  215.  */
  216.  
  217. bool
  218. join_clause_p (clause)
  219.      LispValue clause ;
  220. {
  221.     LispValue leftop = (LispValue) get_leftop(clause);
  222.     LispValue rightop = (LispValue) get_rightop(clause);
  223.  
  224.     if (!is_clause(clause))
  225.         return false;
  226.     
  227.     /*
  228.      * One side of the clause (i.e. left or right operands)
  229.      * must either be a var node ...
  230.      */
  231.     if (IsA(leftop,Var) || IsA(rightop,Var))
  232.         return true;
  233.  
  234.     /*
  235.      * ... or a func node.
  236.      */
  237.     if (consp(leftop) && IsA(CAR(leftop),Func))
  238.         return(true);
  239.     if (consp(rightop) && IsA(CAR(rightop),Func))
  240.         return true;
  241.       return(false);
  242. }
  243.  
  244. /*    
  245.  *        qual-clause-p
  246.  *    
  247.  *        Returns t iff 'clause' is a valid qualification clause.
  248.  *    
  249.  */
  250.  
  251. /*  .. create_nestloop_node, in-line-lambda%598037345
  252.  */
  253. bool
  254. qual_clause_p (clause)
  255.      LispValue clause ;
  256. {
  257.     if (!is_clause(clause))
  258.     return false;
  259.  
  260.     if (IsA (get_leftop (clause),Var) &&
  261.     IsA (get_rightop (clause),Const))
  262.     {
  263.     return(true);
  264.     }
  265.     else if (IsA (get_rightop(clause),Var) &&
  266.          IsA (get_leftop(clause),Const))
  267.     {
  268.     return(true);
  269.     }
  270.     return(false);
  271. }
  272.  
  273. /*    
  274.  *        fix-opid
  275.  *    
  276.  *    Calculate the opfid from the opno...
  277.  *    
  278.  *        Returns nothing.
  279.  *    
  280.  */
  281.  
  282. /*  .. fix-opid, fix-opids
  283.  */
  284. void
  285. fix_opid (clause)
  286.      LispValue clause ;
  287. {
  288.  
  289.     Oper oper;
  290.  
  291.     if(null(clause) || single_node (clause)) {
  292.         ;
  293.     } 
  294.     else if (or_clause (clause)) {
  295.         fix_opids (get_orclauseargs (clause));
  296.     } 
  297.     else if (is_funcclause (clause)) {
  298.         fix_opids (get_funcargs (clause));
  299.     } 
  300.     else if (IsA(clause,ArrayRef)) {
  301.         fix_opid(get_refindexpr((ArrayRef)clause));
  302.         fix_opid(get_refexpr((ArrayRef)clause));
  303.     }
  304.     else if (not_clause (clause)) {
  305.         fix_opid (get_notclausearg (clause));
  306.     } 
  307.     else if (is_clause (clause)) {
  308.         replace_opid(get_op(clause));
  309.         fix_opid ((LispValue)get_leftop (clause));
  310.         fix_opid ((LispValue)get_rightop (clause));
  311.     }
  312.  
  313. } /* fix_opid */
  314.  
  315. /*    
  316.  *        fix-opids
  317.  *    
  318.  *    Calculate the opfid from the opno for all the clauses...
  319.  *    
  320.  *        Returns its argument.
  321.  *    
  322.  */
  323.  
  324. /*  .. create_scan_node, fix-opid, preprocess-targetlist, query_planner
  325.  */
  326. LispValue
  327. fix_opids (clauses)
  328.      LispValue clauses ;
  329. {
  330.     LispValue clause;
  331.     for (clause = clauses ; clause != LispNil ; clause = CDR(clause) ) 
  332.       fix_opid(CAR(clause));
  333.     return(clauses);
  334. }
  335.  
  336. /*    
  337.  *        get_relattval
  338.  *    
  339.  *        For a non-join clause, returns a list consisting of the 
  340.  *            relid,
  341.  *            attno,
  342.  *            value of the CONST node (if any), and a
  343.  *            flag indicating whether the value appears on the left or right
  344.  *                of the operator and whether the value varied.
  345.  *
  346.  * OLD OBSOLETE COMMENT FOLLOWS:
  347.  *        If 'clause' is not of the format (op var node) or (op node var),
  348.  *        or if the var refers to a nested attribute, then -1's are returned for
  349.  *        everything but the value  a blank string "" (pointer to \0) is
  350.  *        returned for the value if it is unknown or null.
  351.  * END OF OLD OBSOLETE COMMENT.
  352.  * NEW COMMENT:
  353.  * when defining rules one of the attibutes of the operator can
  354.  * be a Param node (which is supposed to be treated as a constant).
  355.  * However as there is no value specified for a parameter until run time
  356.  * this routine used to return "" as value, which made 'compute_selec'
  357.  * to bomb (because it was expecting a lisp integer and got back a lisp
  358.  * string). Now the code returns a plain old good "lispInteger(0)".
  359.  *    
  360.  */
  361.  
  362. /*  .. compute_selec, get_relattvals
  363.  */
  364. LispValue
  365. get_relattval (clause)
  366.      LispValue clause ;
  367. {
  368.     Var left = get_leftop (clause);
  369.     Var right = get_rightop (clause);
  370.     
  371.     if(is_clause (clause) && IsA (left,Var) && 
  372.        !var_is_mat (left) && IsA (right,Const)) {
  373.     if(!null(right)) {
  374.         return(lispCons (lispCopy(CAR(get_varid (left))),
  375.               lispCons(lispInteger(get_varattno (left)),
  376.                  lispCons(lispInteger(get_constvalue((Const)right)),
  377.                       lispCons(lispInteger(
  378.                         (_SELEC_CONSTANT_RIGHT_ |
  379.                            _SELEC_IS_CONSTANT_)),
  380.                          LispNil)))));
  381.     } else {
  382.         return(lispCons (lispCopy(CAR(get_varid (left))),
  383.           lispCons(lispInteger(get_varattno (left)),
  384.                /* lispCons(lispString(""), */
  385.                lispCons(lispInteger(0),
  386.                     lispCons((lispInteger
  387.                           (_SELEC_CONSTANT_RIGHT_ |
  388.                            _SELEC_NOT_CONSTANT_)),
  389.                          LispNil)))));
  390.     } 
  391.     } /* if (is_clause(clause . . . */ 
  392.  
  393.     else if (is_clause(clause) &&
  394.          is_funcclause((LispValue)left) &&
  395.          IsA(right,Const))
  396.     {
  397.         return(lispCons(lispCopy(CAR(get_varid((Var)CAR(get_funcargs((LispValue)left))))),
  398.               lispCons(lispInteger(InvalidAttributeNumber),
  399.                  lispCons(lispInteger(get_constvalue((Const)right)),
  400.                     lispCons(lispInteger(
  401.                           (_SELEC_CONSTANT_RIGHT_ |
  402.                            _SELEC_IS_CONSTANT_)),
  403.                          LispNil)))));
  404.     }
  405.     
  406.     /*
  407.      * XXX both of these func clause handling if's seem wrong to me.
  408.      *     they assume that the first argument is the Var.  It could
  409.      *     not handle (for example) f(1, emp.name).  I think I may have
  410.      *     been assuming no constants in functional index scans when I
  411.      *     implemented this originally (still currently true).
  412.      *     -mer 10 Aug 1992
  413.      */
  414.     else if (is_clause(clause) &&
  415.          is_funcclause((LispValue)right) &&
  416.          IsA(left,Const))
  417.     {
  418.         return(lispCons(lispCopy(CAR(get_varid((Var)CAR(get_funcargs((LispValue)right))))),
  419.               lispCons(lispInteger(InvalidAttributeNumber),
  420.                  lispCons(lispInteger(get_constvalue ((Const)left)),
  421.                     lispCons(lispInteger(
  422.                           (_SELEC_IS_CONSTANT_)),
  423.                          LispNil)))));
  424.     }
  425.     
  426.     else if (is_clause (clause) && IsA (right,Var) &&
  427.          ! var_is_mat (right) && IsA (left,Const)) {
  428.     if (!null (left)) {
  429.         return(lispCons(lispCopy(CAR(get_varid (right))),
  430.            lispCons(lispInteger(get_varattno(right)),
  431.                 lispCons(lispInteger(get_constvalue ((Const)left)),
  432.                      lispCons(lispInteger(_SELEC_IS_CONSTANT_),
  433.                           LispNil)))));
  434.     } else {
  435.         return(lispCons (lispCopy(CAR(get_varid (right))),
  436.             lispCons(lispInteger(get_varattno (right)),
  437.                  /* lispCons(lispString(""), */
  438.                  lispCons(lispInteger(0),
  439.                       lispCons(lispInteger(_SELEC_NOT_CONSTANT_),
  440.                            LispNil)))));
  441.     } 
  442.     } else  {
  443.     /*    One or more of the operands are expressions 
  444.           (e.g., oper clauses
  445.           */
  446.     return(lispCons (lispInteger(_SELEC_VALUE_UNKNOWN_),
  447.           lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  448.                /* lispCons(lispString(""), */
  449.                lispCons(lispInteger(0),
  450.                     lispCons(lispInteger(_SELEC_NOT_CONSTANT_),
  451.                          LispNil)))));
  452.     }               
  453. }
  454.  
  455. /*    
  456.  *        get_relsatts
  457.  *    
  458.  *        Returns a list 
  459.  *            ( relid1 attno1 relid2 attno2 )
  460.  *        for a joinclause.
  461.  *    
  462.  *        If the clause is not of the form (op var var) or if any of the vars
  463.  *        refer to nested attributes, then -1's are returned.
  464.  *    
  465.  */
  466.  
  467. /*  .. compute_selec   */
  468.  
  469. LispValue
  470. get_relsatts (clause)
  471.      LispValue clause ;
  472. {
  473.     Var left = get_leftop (clause);
  474.     Var right = get_rightop (clause);
  475.     bool isa_clause = false;
  476.     
  477.     bool var_left = ( (IsA(left,Var) && !var_is_mat (left) ) ?true : false);
  478.     bool var_right = ( (IsA(right,Var) && !var_is_mat(right)) ? true:false);
  479.     bool varexpr_left = (bool)((IsA(left,Func) || IsA (left,Oper)) &&
  480.                    pull_var_clause ((LispValue)left) );
  481.     bool varexpr_right = (bool)(( IsA(right,Func) || IsA (right,Oper)) &&
  482.                 pull_var_clause ((LispValue)right));
  483.     
  484.     isa_clause = is_clause (clause);
  485.     if(isa_clause && var_left
  486.        && var_right) {
  487.     return(lispCons (lispCopy(CAR(get_varid (left))),
  488.              lispCons(lispCopy(CADR(get_varid (left))),
  489.                   lispCons(lispCopy(CAR(get_varid (right))),
  490.                        lispCons(lispCopy
  491.                             (CADR(get_varid (right))),
  492.                             LispNil)))));
  493.     } else if ( isa_clause && var_left && varexpr_right ) {
  494.     return(lispCons(lispCopy(CAR(get_varid (left))),
  495.             lispCons(lispCopy(CADR(get_varid (left))),
  496.                  lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  497.                       lispCons(lispInteger
  498.                            (_SELEC_VALUE_UNKNOWN_),
  499.                            LispNil)))));
  500.     } else if ( isa_clause && varexpr_left && var_right) {
  501.     return(lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  502.             lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  503.                  lispCons(lispCopy(CAR(get_varid (right))),
  504.                       lispCons(lispCopy(CADR(get_varid(right))),
  505.                            LispNil)))));
  506.     } else {
  507.     return(lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  508.             lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  509.                  lispCons(lispInteger(_SELEC_VALUE_UNKNOWN_),
  510.                       lispCons(lispInteger
  511.                            (_SELEC_VALUE_UNKNOWN_),
  512.                            LispNil)))));
  513.     }
  514. }
  515.  
  516. bool
  517. is_clause(clause)
  518.      LispValue clause;
  519. {
  520.     if (consp (clause)) {
  521.     LispValue oper = clause_head(clause);
  522.  
  523.     if (IsA(oper,Oper))
  524.       return(true);
  525.     }
  526.     
  527.     return(false);
  528.     
  529. }
  530.  
  531. void
  532. CommuteClause(clause)
  533.     LispValue clause;
  534. {
  535.     LispValue temp;
  536.     Oper commu;
  537.     OperatorTupleForm commuTup;
  538.     HeapTuple heapTup;
  539.  
  540.     if (!(is_clause(clause) &&
  541.       IsA(CAR(clause),Oper)))
  542.     return;
  543.  
  544.     heapTup = (HeapTuple)
  545.     get_operator_tuple( get_commutator(get_opno((Oper)CAR(clause))) );
  546.  
  547.     if (heapTup == (HeapTuple)NULL)
  548.     return;
  549.  
  550.     commuTup = (OperatorTupleForm)GETSTRUCT(heapTup);
  551.  
  552.     commu = MakeOper(heapTup->t_oid,
  553.          InvalidObjectId, 
  554.          get_oprelationlevel((Oper)CAR(clause)),
  555.          commuTup->oprresult,
  556.          get_opsize((Oper)CAR(clause)),
  557.          NULL);
  558.  
  559.     /*
  560.      * reform the clause -> (operator func/var constant)
  561.      */
  562.     CAR(clause) = (LispValue)commu;
  563.     temp = CADR(clause);
  564.     CADR(clause) = CADDR(clause);
  565.     CADDR(clause) = temp;
  566. }
  567.